View Javadoc

1   // HighResolutionTimer.java, created Tue Dec 10 14:02:07 2002 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Runtime;
5   
6   import joeq.Bootstrap.MethodInvocation;
7   import joeq.Class.jq_Class;
8   import joeq.Class.jq_Method;
9   import joeq.Class.jq_NameAndDesc;
10  import joeq.Main.jq;
11  import joeq.Memory.CodeAddress;
12  import joeq.Memory.HeapAddress;
13  import joeq.Memory.StackAddress;
14  import joeq.Runtime.SystemInterface.ExternalLink;
15  import joeq.Runtime.SystemInterface.Library;
16  import jwutil.util.Assert;
17  
18  /***
19   * @author John Whaley <jwhaley@alum.mit.edu>
20   * @version $Id: HighResolutionTimer.java 1941 2004-09-30 03:37:06Z joewhaley $
21   */
22  public class HighResolutionTimer {
23      private static boolean native_library_present;
24  
25      static {
26          try {
27              System.loadLibrary("timer");
28              native_library_present = true;
29          } catch (Throwable _) {}
30      }
31      public static native long ticks();
32      public static final double TICKS_PER_SECOND = 2e9;
33      public static void main(String[] args) throws Exception {
34          for (int i=0; i<10; ++i) {
35              System.out.println("Now: "+now());
36          }
37      }
38  
39      private static long counter_frequency = 0L;
40  
41      public static final void init() {
42          if (QueryPerformanceFrequency != null) {
43              counter_frequency = query_performance_frequency();
44          }
45      }
46  
47      public static final double now() {
48          if (QueryPerformanceCounter != null) {
49              if (counter_frequency == 0L) init();
50              long l = query_performance_counter();
51              return (double)l / counter_frequency;
52          } else if (gettimeofday != null) {
53              long l = get_time_of_day();
54              int sec = (int) (l >> 32);
55              int usec = (int) l;
56              return ((double)sec) * 1000000 + usec;
57          } else if (native_library_present) {
58              return ticks() / TICKS_PER_SECOND;
59          } else {
60              return 0.;
61          }
62      }
63  
64      private static long query_performance_frequency() {
65          try {
66              CodeAddress a = QueryPerformanceFrequency.resolve();
67              StackAddress b = StackAddress.alloca(8);
68              Unsafe.pushArgA(b);
69              Unsafe.getThreadBlock().disableThreadSwitch();
70              byte rc = (byte) Unsafe.invoke(a);
71              Unsafe.getThreadBlock().enableThreadSwitch();
72              if (rc != 0) {
73                  // error occurred (?)
74              }
75              long v = b.peek8();
76              return v;
77          } catch (Throwable t) { Assert.UNREACHABLE(); }
78          return 0L;
79      }
80  
81      private static long query_performance_counter() {
82          try {
83              CodeAddress a = QueryPerformanceCounter.resolve();
84              StackAddress b = StackAddress.alloca(8);
85              Unsafe.pushArgA(b);
86              Unsafe.getThreadBlock().disableThreadSwitch();
87              byte rc = (byte) Unsafe.invoke(a);
88              Unsafe.getThreadBlock().enableThreadSwitch();
89              if (rc != 0) {
90                  // error occurred (?)
91              }
92              long v = b.peek8();
93              return v;
94          } catch (Throwable t) { Assert.UNREACHABLE(); }
95          return 0L;
96      }
97      
98      private static long get_time_of_day() {
99          try {
100             CodeAddress a = gettimeofday.resolve();
101             StackAddress b = StackAddress.alloca(8);
102             Unsafe.pushArgA(HeapAddress.getNull());
103             Unsafe.pushArgA(b);
104             Unsafe.getThreadBlock().disableThreadSwitch();
105             int rc = (int) Unsafe.invoke(a);
106             Unsafe.getThreadBlock().enableThreadSwitch();
107             if (rc != 0) {
108                 // error occurred (?)
109             }
110             long v = b.peek8();
111             return v;
112         } catch (Throwable t) { Assert.UNREACHABLE(); }
113         return 0L;
114     }
115     
116     static ExternalLink QueryPerformanceFrequency;
117     static ExternalLink QueryPerformanceCounter;
118     static ExternalLink gettimeofday;
119     
120     static {
121         if (jq.RunningNative) boot();
122         else if (jq.on_vm_startup != null) {
123             jq_Class c = (jq_Class) Reflection.getJQType(HighResolutionTimer.class);
124             jq_Method m = c.getDeclaredStaticMethod(new jq_NameAndDesc("boot", "()V"));
125             MethodInvocation mi = new MethodInvocation(m, null);
126             jq.on_vm_startup.add(mi);
127         }
128     }
129     
130     public static void boot() {
131         Library kernel32 = SystemInterface.registerLibrary("kernel32");
132         Library c = SystemInterface.registerLibrary("libc.so.6");
133 
134         if (kernel32 != null) {
135             QueryPerformanceFrequency = kernel32.resolve("QueryPerformanceFrequency");
136             QueryPerformanceCounter = kernel32.resolve("QueryPerformanceCounter");
137         } else {
138             QueryPerformanceFrequency = QueryPerformanceCounter = null;
139         }
140 
141         if (c != null) {
142             gettimeofday = c.resolve("gettimeofday");
143         } else {
144             gettimeofday = null;
145         }
146     }
147 }